#include <libseminix/client.h>
#include <libseminix/syscall.h>

int seminix_online_cpumask(cpumask_t *cpumask)
{
    int ret, op = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_ONLINECPUMASK,
        .sysctl.cpumask = CPU_MASK_NONE,
    };

    if (!cpumask)
        return -SERRNO_EINVAL;

    ret = __syscall(SYS_seminix_SysCtl, op, &sysctl);
    if (ret)
        return ret;

    cpumask_copy(cpumask, &sysctl.sysctl.cpumask);

    return 0;
}

int seminix_cpu_nr_task(int cpu)
{
    int ret, op = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_CPU_NR_TASK,
        .sysctl.cpu_task = {
            .cpu = cpu,
        },
    };

    ret = __syscall(SYS_seminix_SysCtl, op, &sysctl);
    if (ret)
        return ret;

    return sysctl.sysctl.cpu_task.nr_task;
}

int seminix_get_tcb_weight(int tcb, unsigned long *weight)
{
    int ret, op = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_TCB_WEIGHT,
        .sysctl.tcb_wi = {
            .tcb = tcb,
        },
    };

    ret = __syscall(SYS_seminix_SysCtl, op, &sysctl);
    if (ret)
        return ret;

    if (weight)
        *weight = sysctl.sysctl.tcb_wi.weight;

    return 0;
}

int seminix_get_cpu_weight(int cpu, unsigned long *weight)
{
    int ret, cmd = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_CPU_WEIGHT,
        .sysctl.cpu_wi = {
            .cpu = cpu,
        },
    };

    ret = __syscall(SYS_seminix_SysCtl, cmd, &sysctl);
    if (ret)
        return ret;

    if (weight)
        *weight = sysctl.sysctl.cpu_wi.weight;

    return 0;
}

unsigned long seminix_get_ipcbuffer(void)
{
    int ret, cmd = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_IPCBUFFER,
        .sysctl.ipcbuf = {
            .uaddr = 0,
        },
    };

    ret = __syscall(SYS_seminix_SysCtl, cmd, &sysctl);
    if (ret)
        return 0;

    return sysctl.sysctl.ipcbuf.uaddr;
}

unsigned long seminix_get_pagesize(void)
{
    int op = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_PAGESIZE,
        .sysctl.pagesize = 0,
    };

    __syscall(SYS_seminix_SysCtl, op, &sysctl);

    return sysctl.sysctl.pagesize;
}

unsigned long seminix_get_nr_pages_min(void)
{
    int op = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_NR_PAGES_MIN,
        .sysctl.nr_pages_min = 0,
    };

    __syscall(SYS_seminix_SysCtl, op, &sysctl);

    return sysctl.sysctl.nr_pages_min;
}

int seminix_set_nr_pages_min(int sysctl, unsigned long nr_pages)
{
    int op = SYSCTL_CMD_SET;
    sysctl_t _sysctl = {
        .type = SYSCTL_TYPE_NR_PAGES_MIN,
        .sysctl.nr_pages_min = nr_pages,
    };

    return __syscall(SYS_seminix_SysCtl, op, &_sysctl, sysctl);
}

unsigned long seminix_get_mmapcount_max(void)
{
    int op = SYSCTL_CMD_GET;
    sysctl_t sysctl = {
        .type = SYSCTL_TYPE_MMAPCOUNT_MAX,
        .sysctl.mmapcount_max = 0,
    };

    __syscall(SYS_seminix_SysCtl, op, &sysctl);

    return sysctl.sysctl.mmapcount_max;
}

int seminix_set_mmapcount_max(int sysctl, unsigned long mmapcount_max)
{
    int op = SYSCTL_CMD_SET;
    sysctl_t _sysctl = {
        .type = SYSCTL_TYPE_MMAPCOUNT_MAX,
        .sysctl.mmapcount_max = mmapcount_max,
    };

    return __syscall(SYS_seminix_SysCtl, op, &_sysctl, sysctl);
}
